package core.proto.search;

import org.apache.commons.io.FilenameUtils;
import org.apache.lucene.document.Document;
import org.apache.lucene.search.Hits;

import static app.constants.CollabVizConstants.*;


import core.proto.Util;

import prefuse.data.Tuple;
import prefuse.data.search.KeywordSearchTupleSet;
import prefuse.data.search.LuceneSearcher;
import prefuse.util.StringLib;
import prefuse.visual.EdgeItem;
import prefuse.visual.NodeItem;

import java.util.*;

/**
 * Extends the {@link prefuse.data.search.KeywordSearchTupleSet} to provide 
 * custom behavior.
 * 
 * Specifically, allows us to get the matching tuple of the search based on comparison 
 * of the path field of in the data {@link prefuse.data.Tuple} object. 
 * This basically lets us use the same index as the one used in searching
 * the {@link core.proto.FileTree} component.   
 */
public class LuceneSearchTupleSet extends KeywordSearchTupleSet {
	Map<String, Tuple> nameToTupleMap;
	static final String NAME = "name";

	public LuceneSearchTupleSet(LuceneSearcher searcher){
		super(searcher);
		nameToTupleMap = new HashMap<String, Tuple>();
	}

	@Override
	/**
	 * Tuple matches if the document's name matches the 
	 * name field stored in the tuple. This is specific 
	 * to our application, where we want to return search
	 * results that match the ones we want. 
	 */
	protected Tuple getMatchingTuple(Document doc){
		// We will match on the file's name since that's likely to be unique anyway. 
		String path = doc.get(LuceneIndexCreationUtil.FILENAME_FIELD);
		return nameToTupleMap.get(path);
	}

	/**
	 * Exact same source code as prefuse but 
	 * suppress the annoying parse error messages 
	 * since that's something we cannot control in 
	 * the super old version of Lucene prefuse uses. 
	 */
	public void search(String query){
		if (query == null)
			query = "";

		if (query.equals(m_query))
			return; // no change

		Tuple[] rem = clearInternal();
		m_query = query;

		query.trim();
		if (query.length() == 0) {
			this .fireTupleEvent(null, DELETE);
			return;
		}

		m_lucene.setReadMode(true);
		try {
			Hits hits = m_lucene.search(query);
			for (int i = 0; i < hits.length(); i++) {
				Tuple t = getMatchingTuple(hits.doc(i));
				addInternal(t);
			}
			Tuple[] add = getTupleCount() > 0 ? toArray() : null;
			fireTupleEvent(add, rem);
		} catch (Exception e) {
		}
	}

	/**
	 * Overridden to do nothing. We don't need to create index since 
	 * it's already created for use in the file tree area. 
	 */
	public void index(Tuple t, String field){
		// No op. 
	}

	/**
	 * Adds a Prefuse Tuple object to the hashmap from the search result key 
	 * (currently the document name) to the Tuple object (the matching search
	 * result). 
	 * @param t
	 */
	public void addTupleToMap(Tuple t){
		if (t instanceof NodeItem){
			nameToTupleMap.put(t.getString(NAME), t);
		}
	}
}
